﻿using System;
using System.Collections.Generic;
using System.Linq;
using StockAccessors.Interdin.Model;

namespace StockAccessors.Interdin.Engine
{
	internal class DetailsLinkManager : IDisposable
	{
		#region Attributes

		private readonly FuturesPageReader _futuresPageReader;
		private readonly CfdPageReader _cfdPageReader;

		private readonly Dictionary<string, DetailsLink> _cfdDetails;
		private readonly Dictionary<string, DetailsLink> _futuresDetails;

		private readonly object _dictionaryLock;

		#endregion

		#region Properties

		public Dictionary<string, DetailsLink> Details
		{
			get
			{
				lock (_dictionaryLock)
				{
					return _cfdDetails.Concat(_futuresDetails).ToDictionary(s => s.Key, d => d.Value);	
				}
			}
		}

		#endregion

		#region Public Methods

		public DetailsLinkManager(FuturesPageReader futuresPageReader, CfdPageReader cfdPageReader)
		{
			_dictionaryLock = new object();
			_cfdDetails = new Dictionary<string, DetailsLink>();
			_futuresDetails = new Dictionary<string, DetailsLink>();

			_futuresPageReader = futuresPageReader;
			_cfdPageReader = cfdPageReader;

			_futuresPageReader.PropertyChanged += FuturesPageReader_PropertyChanged; // Disposed
			_cfdPageReader.PropertyChanged += CfdPageReader_PropertyChanged; // Disposed
		}

		#endregion

		#region Event Handlers

		private void CfdPageReader_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
		{
			if (e.PropertyName == "Page")
			{
				this.UpdateCfdLinks();
			}
		}

		private void FuturesPageReader_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
		{
			if (e.PropertyName == "Page")
			{
				this.UpdateFuturesLinks();
			}
		}

		#endregion

		#region Private Methods

		private void UpdateCfdLinks()
		{
			lock (_dictionaryLock)
			{
				_cfdDetails.Clear();

				foreach (WebCfd item in _cfdPageReader.Page.ContinuousMarketGroup.Cfds)
				{
					_cfdDetails.Add(item.Symbol, item.DetailsLink);
				}
				foreach (WebCfd item in _cfdPageReader.Page.EuroStoxx50Group.Cfds)
				{
					_cfdDetails.Add(item.Symbol, item.DetailsLink);
				}
				foreach (WebCfd item in _cfdPageReader.Page.Ibex35Group.Cfds)
				{
					_cfdDetails.Add(item.Symbol, item.DetailsLink);
				}
			}
		}

		private void UpdateFuturesLinks()
		{
			lock (_dictionaryLock)
			{
				_futuresDetails.Clear();

				foreach (WebFuture item in _futuresPageReader.Page.CurrencyGroup.Futures)
				{
					_futuresDetails.Add(item.Symbol, item.DetailsLink);
				}
				foreach (WebFuture item in _futuresPageReader.Page.EnergyAndMaterialsGroup.Futures)
				{
					_futuresDetails.Add(item.Symbol, item.DetailsLink);
				}
				foreach (WebFuture item in _futuresPageReader.Page.EurexGroup.Futures)
				{
					_futuresDetails.Add(item.Symbol, item.DetailsLink);
				}
				foreach (WebFuture item in _futuresPageReader.Page.MeffGroup.Futures)
				{
					_futuresDetails.Add(item.Symbol, item.DetailsLink);
				}
				foreach (WebFuture item in _futuresPageReader.Page.OtherIndexGroup.Futures)
				{
					_futuresDetails.Add(item.Symbol, item.DetailsLink);
				}
			}
		}

		#endregion

		#region IDisposable

		protected bool Disposed { get; private set; }

		private void Dispose(bool disposing)
		{
			if (!this.Disposed)
			{
				this.InternalDispose(disposing);
			}

			this.Disposed = true;
		}

		protected virtual void InternalDispose(bool disposing)
		{
			if (disposing)
			{
				_futuresPageReader.PropertyChanged -= FuturesPageReader_PropertyChanged;
				_cfdPageReader.PropertyChanged -= CfdPageReader_PropertyChanged;
			}
			
			// Dispose here only unmanaged objects 
			// Don’t use managed objects here because maybe 
			// they have been finalized already
		}

		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}

		~DetailsLinkManager()
		{
			this.Dispose(false);
		}

		#endregion
	}
}
